package funs

import (
	"base/lang"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/golang-jwt/jwt/v5"
	"github.com/mojocn/base64Captcha"
	"github.com/spf13/viper"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
)

type apiResult struct {
	Code    int
	Message string
	Data    any
}

// 返回空变量
var EmptyData = []any{}

// jwt 加密密钥
var secret = "天王盖地虎，宝塔镇河妖"

// 读取配置文件
func Env(key string) any {
	viper.SetConfigName(".env") //配置文件名称
	viper.SetConfigType("yml")
	basePath, e := os.Getwd()

	basePath = filepath.Dir(basePath)

	if e != nil {
		fmt.Printf("获取路径错误：%s", e)
	}
	viper.AddConfigPath(basePath)
	err := viper.ReadInConfig() //查找并读取文件
	if err != nil {
		fmt.Println(fmt.Errorf("fatal error config file: %w", err))
	}

	res := viper.Get(key)

	switch reflect.TypeOf(res).Kind() {
	case reflect.Int:
		return res.(int)
	case reflect.String:
		return res.(string)
	}
	return nil
}

// 读取配置文件
func EnvExists() error {
	basePath, e := os.Getwd()
	if e != nil {
		fmt.Printf("获取路径错误：%s", e)
	}

	filename := fmt.Sprintf("%s/%s", basePath, ".env.yml")

	// 使用 os.Stat 函数获取文件信息
	_, err := os.Stat(filename)

	if os.IsNotExist(err) {
		// 文件不存在
		return errors.New(fmt.Sprintf("配置文件不存在:%s", filename))
	} else if err != nil {
		// 出现其他错误
		return errors.New(fmt.Sprintf("验证文件函数错误:%s", filename))
	}

	return nil
}

// 接口返回
func Success(code int, msg string, data any, reqLang string) apiResult {

	result := apiResult{}
	result.Message = lang.SusMap[reqLang][msg]
	result.Code = code
	result.Data = data

	return result

}

func Error(code int, msg string, data any, reqLang string) apiResult {

	result := apiResult{}
	result.Message = lang.ErrMap[reqLang][msg]
	result.Code = code
	result.Data = data

	return result

}

// 获取map 内的其中一个Key
func MapColumn(data []map[string]any, key string) []any {

	result := []any{}

	for _, v := range data {
		result = append(result, v[key])
	}

	return result
}

// 获取验证码
func GetCode() (id, bs64 string, err error) {
	captcha := base64Captcha.NewCaptcha(base64Captcha.DefaultDriverDigit, base64Captcha.DefaultMemStore)
	return captcha.Generate()
}

// 创建token
func CreateToken(data *jwt.MapClaims) (string, error) {
	// 创建声明
	claims := jwt.NewWithClaims(jwt.SigningMethodHS256, data)

	// 生成 JWT
	token, err := claims.SignedString([]byte(secret))

	return token, err
}

// token 获取用户信息
func TokenGetData(token string) (map[string]any, error) {

	parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
		// 校验签名方法
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("签名验证错误")
		}
		return []byte(secret), nil
	})

	if err != nil {
		return nil, fmt.Errorf("Token 错误")
	}

	// 验证并获取声明
	if claims, ok := parsedToken.Claims.(jwt.MapClaims); ok && parsedToken.Valid {
		return claims, nil
	} else {
		return nil, fmt.Errorf("Token 获取数据失败")
	}
}

func ToString(data any) (string, error) {

	//数据为nil
	if data == nil {
		return "", nil
	}

	switch reflect.TypeOf(data).Kind() {
	case reflect.Uint8:
		return strconv.FormatUint(uint64(data.(uint8)), 10), nil
	case reflect.Uint:
		return strconv.FormatUint(uint64(data.(uint)), 10), nil
	case reflect.Uint16:
		return strconv.FormatUint(uint64(data.(uint16)), 10), nil
	case reflect.Uint32:
		return strconv.FormatUint(uint64(data.(uint32)), 10), nil
	case reflect.Uint64:
		return strconv.FormatUint(data.(uint64), 10), nil
	case reflect.Int:
		return strconv.FormatInt(int64(data.(int)), 10), nil
	case reflect.Int8:
		return strconv.FormatInt(int64(data.(int8)), 10), nil
	case reflect.Int16:
		return strconv.FormatInt(int64(data.(int16)), 10), nil
	case reflect.Int32:
		return strconv.FormatInt(int64(data.(int32)), 10), nil
	case reflect.Int64:
		return strconv.FormatInt(data.(int64), 10), nil
	case reflect.Map:
		str, err := GetJsonData(data)
		return str, err
	case reflect.Slice:
		str, err := GetJsonData(data)
		return str, err
	case reflect.Bool:
		return strconv.FormatBool(data.(bool)), nil
	case reflect.Chan:
		return "", nil
	case reflect.Func:
		return "", nil
	case reflect.Uintptr:
		return "", nil
	}
	return data.(string), nil
}

// 将结构体转为json
func GetJsonData(data any) (string, error) {

	//将结构体 转为json
	jsonData, err := json.Marshal(data)

	return string(jsonData), err
}
